package com.cjack.frenchexcel.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.cjack.frenchexcel.config.ErrorCodeDefine;
import com.cjack.frenchexcel.config.LayPage;
import com.cjack.frenchexcel.config.PrivateConfig;
import com.cjack.frenchexcel.dao.*;
import com.cjack.frenchexcel.exception.BankCardNotExsitException;
import com.cjack.frenchexcel.exception.CommonException;
import com.cjack.frenchexcel.exception.ConsumerImportRepeatException;
import com.cjack.frenchexcel.exception.DateErrorException;
import com.cjack.frenchexcel.model.*;
import com.cjack.frenchexcel.table.*;
import com.cjack.frenchexcel.util.*;
import com.sargeraswang.util.ExcelUtil.ExcelLogs;
import com.sargeraswang.util.ExcelUtil.ExcelUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.zeroturnaround.zip.ZipUtil;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.io.*;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.*;

/**
 * Created by root on 10/5/19
 */
@Service
public class ConsumerRecordService {

    @Autowired
    private ConsumerRecordDao dao;
    @Autowired
    private MooncardDao mooncardDao;
    @Autowired
    private UserAdminDao userAdminDao;
    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    private CooperativeNumberDao cooperativeNumberDao;
    @Autowired
    private CloudDiskDao cloudDiskDao;
    @Autowired
    private MooncardCardDao mooncardCardDao;
    @Autowired
    private CloudDiskService cloudDiskService;

    @Value("${file.upload.baseServerDir}")
    String baseServerDir;
    @Value("${file.upload.baseClientDir}")
    String baseClientDir;
    @Value("${file.upload.spelitor}")
    String spelitor;

    public JSONObject exportAsExcel(ConsumerRecordConditionModel condition) throws CommonException {

        String fileType = "consumerExportExcel";
        //先创建excel空文件
        String fileName = FileUtils.getXlsxFileName();
        String dumic = fileType + spelitor + FileUtils.getDirByDate();//动态的这一截路径
        //服务器保存文件的目录
        String destDir = baseServerDir + dumic;
        //供浏览器客户端访问的目录
        String clientDir = baseClientDir + dumic;
        //处理目录不存在则创建
        FileUtils.handleDir(destDir);
        File dest = new File(destDir + spelitor + fileName);
        //需要导出的数据
        List<ConsumerRecordModel> records = this.list(condition);
        List<ConsumerExportModel> exportDatas = build(records);
        //导出的列 title信息
        Map<String, String> col = ConsumerExportModel.getColMap();
        OutputStream out;
        try {
            out = new FileOutputStream(dest);
            ExcelUtil.exportExcel(col, exportDatas, out);
            out.close();
        } catch (FileNotFoundException e) {
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR, "导出excel失败");
        } catch (IOException e) {
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR, "导出excel失败");
        }

        //将导出成功的excel地址和导出数据的条数返回给客户端
        JSONObject json = new JSONObject();
        json.put("exportCount", exportDatas.size());
        json.put("filePath", clientDir + spelitor + fileName);
        return json;
    }

    public JSONObject exportBankStatement(ConsumerRecordConditionModel condition) {
        String fileType = "consumerBankStatementExcel";
        //先创建excel空文件
        String fileName = FileUtils.getXlsxFileName();
        String dumic = fileType + spelitor + FileUtils.getDirByDate();//动态的这一截路径
        //服务器保存文件的目录
        String destDir = baseServerDir + dumic;
        //供浏览器客户端访问的目录
        String clientDir = baseClientDir + dumic;
        //处理目录不存在则创建
        FileUtils.handleDir(destDir);
        File dest = new File(destDir + spelitor + fileName);
        //需要导出的原始消费记录数据
        List<ConsumerRecordModel> records = this.list(condition);
        //组装最终导出的数据集
        List<ConsumerBankStatementModel> exportDataList;
        try {
            exportDataList = buildBankStatement(records);
            //导出的列 title信息
            Map<String, String> col = ConsumerBankStatementModel.getColMap();
            OutputStream out;

            out = new FileOutputStream(dest);
            ExcelUtil.exportExcel(col, exportDataList, out);
            out.close();
        } catch (FileNotFoundException e) {
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR, "导出excel失败");
        } catch (IOException e) {
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR, "导出excel失败");
        }

        //将导出成功的excel地址和导出数据的条数返回给客户端
        JSONObject json = new JSONObject();
        json.put("exportCount", exportDataList.size());
        json.put("filePath", clientDir + spelitor + fileName);
        return json;
    }


    private List<ConsumerExportModel> build(List<ConsumerRecordModel> records) {
        List<ConsumerExportModel> exportDatas = new ArrayList<>();
        for (ConsumerRecordModel record : records) {
            ConsumerExportModel exportData = new ConsumerExportModel();

            exportData.setDateDeDepense(DateFormatUtil.format(record.getDateDeDepense(), DateFormatUtil.DATE_RULE_9));
            List<CooperativeNumberTable> exsits = cooperativeNumberDao.getByName(record.getFournisseur());
            if (CollectionUtils.isNotEmpty(exsits)) {
                CooperativeNumberTable cooperativeNumberTable = exsits.get(0);
                exportData.setCooperativeNumber(cooperativeNumberTable.getNumber());
                exportData.setSimpleName(cooperativeNumberTable.getName());
                exportData.setCity(cooperativeNumberTable.getCity());
                exportData.setAddr(cooperativeNumberTable.getAddr());
                exportData.setEmailCode(cooperativeNumberTable.getEmailCode());
            }
            GoodsTable goodsTable = goodsDao.getByConsumerRecordId(record.getId());
            if (goodsTable != null) {
                exportData.setNumber(goodsTable.getNumber());
                exportData.setType(goodsTable.getName());
            }
            boolean tvaTwenty = "20%".equals(record.getInvoiceRate());
            exportData.setTvaTwenty(tvaTwenty ? "Y" : "N");
            exportData.setTva(record.getInvoiceMoney());
            exportData.setTtc(Math.abs(Double.valueOf(record.getMontantTTC())) + "");
            exportDatas.add(exportData);
        }
        return exportDatas;
    }

    private List<ConsumerBankStatementModel> buildBankStatement(List<ConsumerRecordModel> records) {
        List<ConsumerBankStatementModel> exportDatas = new ArrayList<>();
        BigDecimal creditSum = new BigDecimal(0);
        BigDecimal debitSum = new BigDecimal(0);
        String MMyyyy = null;
        for (ConsumerRecordModel record : records) {
            ConsumerBankStatementModel exportData = new ConsumerBankStatementModel();
            String carteIdentifiant = record.getCarteIdentifiant();
            exportData.setCarteIdentifiant(carteIdentifiant);
            String dateDeDepense = record.getDateDeDepense();
            String format = DateFormatUtil.format(dateDeDepense, DateFormatUtil.DATE_RULE_2, DateFormatUtil.DATE_RULE_14);
            String formatMMyyyy = DateFormatUtil.format(format, DateFormatUtil.DATE_RULE_14, DateFormatUtil.DATE_RULE_5);
            if (MMyyyy == null) {
                MMyyyy = formatMMyyyy;
            }
            exportData.setDateDeDepense(format);
            if (StrUtil.isNotEmpty(record.getCollaborateur())) {
                //根据jobNumber查询合作商数据
                CooperativeNumberTable cooperative = cooperativeNumberDao.findByJobNumberAndName(record.getCollaborateur(), record.getFournisseur());
                String format1 = DateFormatUtil.format(format, DateFormatUtil.DATE_RULE_14, DateFormatUtil.DATE_RULE_13);
                exportData.setMonthYear(format1);
                if (cooperative != null) {
                    exportData.setCooperativeNumber(cooperative.getNumber());
                    exportData.setCooperativeName(cooperative.getName());
                } else {
                    exportData.setCooperativeName(record.getFournisseur());
                }
            }

            String montantTTC = record.getMontantTTC();
            if (montantTTC.contains("-")) {
                String replace = montantTTC.replace("-", "");
                exportData.setCredit(new BigDecimal(replace));
            } else {
                exportData.setDebit(new BigDecimal(montantTTC));
            }
            if (!StringUtils.isEmpty(exportData.getCredit())) {
                BigDecimal credit = exportData.getCredit();
                creditSum = creditSum.add(credit);
            }
            if (!StringUtils.isEmpty(exportData.getDebit())) {
                BigDecimal debit = exportData.getDebit();
                debitSum = debitSum.add(debit);
            }
            exportDatas.add(exportData);
        }

        //手动插入一行数据
        ConsumerBankStatementModel manulAddData = new ConsumerBankStatementModel();
        int size = exportDatas.size();
        int index = size - 1;
        ConsumerBankStatementModel model = exportDatas.get(index);
        String monthLastDay = DateFormatUtil.getMonthLastDay2(model.getDateDeDepense());
        manulAddData.setDateDeDepense(monthLastDay);//当月最后一天
        manulAddData.setCarteIdentifiant(model.getCarteIdentifiant());
        manulAddData.setCooperativeNumber("512000");
        manulAddData.setMonthYear(model.getMonthYear());
        manulAddData.setCooperativeName("BANQUE");
        manulAddData.setCredit(debitSum);
        manulAddData.setDebit(creditSum);
        exportDatas.add(manulAddData);
        return exportDatas;
    }

    public JSONObject exportInvoice(ConsumerRecordConditionModel condition) {
        String fileType = "invoiceExportZip";
        //先创建excel空文件
        String fileName = FileUtils.getZipFileName();
        String dumic = fileType + spelitor + FileUtils.getDirByDate();//动态的这一截路径
        //服务器保存文件的目录
        String destDir = baseServerDir + dumic;
        //供浏览器客户端访问的目录
        String clientDir = baseClientDir + dumic;
        //处理目录不存在则创建
        FileUtils.handleDir(destDir);
        String finalPdfPath = destDir + spelitor + FileUtils.getPdfFileName();
        String zipPath = destDir + spelitor + fileName;
        //需要导出的数据
        List<ConsumerRecordModel> exportDatas = this.listAndSort(condition);
        List<String> pdfs = new ArrayList<>();
        for (int i = 0; i < exportDatas.size(); i++) {
            ConsumerRecordModel exportData = exportDatas.get(i);
            if (StringUtils.isEmpty(exportData.getInvoice()) || exportData.getInvoice().equals("LOSE")) {
                continue;
            }
            String pdfFilePath = FileUtils.transferClientFileUrl(exportData.getInvoice(), baseClientDir, baseServerDir);
            pdfs.add(pdfFilePath);
        }
        try {
            PdfUtil.mergePDF(pdfs.toArray(new String[0]), finalPdfPath);
        } catch (Exception e) {
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR);
        }
        ZipUtil.packEntry(new File(finalPdfPath), new File(zipPath));

        //将导出成功的excel地址和导出数据的条数返回给客户端
        JSONObject json = new JSONObject();
        json.put("exportCount", exportDatas.size());
        json.put("filePath", clientDir + spelitor + fileName);
        return json;
    }

    public static void main(String[] args) {
        List<String> pdfs = new ArrayList<>();
        pdfs.add("123");
        System.out.println(pdfs.toArray(new String[0]));
    }

    /**
     * @param filePath excel的路径
     * @return 返回因为数据库重复而导入失败的数据
     * @throws CommonException
     * @throws FileNotFoundException
     */
    @Transactional
    public JSONObject importFromExcel2(String filePath, Long loginUserId) {
        //1.获取导入数据
        List<NewImportConsumerModel> consumerDataList = getNewImportConsumerModels(filePath);

        //2.数据检查[是否都是同一个卡号的消费记录]
        long count = consumerDataList.stream().map(NewImportConsumerModel::getCarteIdentifiant).distinct().count();
        AssertUtil.assertTrue(count == 1, 7003, "E列不完全一样");

        //3.构建落库数据
        List<ConsumerRecordModel> consumerRecordModels = new ArrayList<>();
        for (NewImportConsumerModel importExcelData : consumerDataList) {
            AssertUtil.assertFalse(StrUtil.isNotEmpty(importExcelData.getMontantTTC1()) && !NumberUtil.isNumber(importExcelData.getMontantTTC1()), ErrorCodeDefine.IMPORT_EXCEL_FAIL, "B列数据存在非数字问题 errorMsg："+importExcelData.getMontantTTC1());
            AssertUtil.assertFalse(StrUtil.isNotEmpty(importExcelData.getMontantTTC2()) && !NumberUtil.isNumber(importExcelData.getMontantTTC2()), ErrorCodeDefine.IMPORT_EXCEL_FAIL, "D列数据存在非数字问题 errorMsg："+importExcelData.getMontantTTC2());
            //根据卡号查询卡信息
            MooncardCardTable cardInfo = mooncardCardDao.findByBankNo(importExcelData.getCarteIdentifiant());
            AssertUtil.assertNotNull(cardInfo, ErrorCodeDefine.INTERFACE_COMMON_ERROR, "卡号不包含");
            String formatDateDeepens = null;
            //如果excel的列类型是日期，这里读取出来的值是 "Mon Mar 02 00:00:00 CST 2020" 这种
            if (!importExcelData.getDateDeDepense().contains("/")) {
                formatDateDeepens = DateFormatUtil.format(new Date(importExcelData.getDateDeDepense()), DateFormatUtil.DATE_RULE_2);
            } else {
                //日 月 年
                String[] arr = importExcelData.getDateDeDepense().split("/");
                formatDateDeepens = arr[2] + "-" + arr[1] + "-" + arr[0];
            }

            //根据员工id查询员工信息
            AdminUserTable adminUserTable = userAdminDao.findOne(cardInfo.getAdminUserId());
            //判断每行ID 卡号对应的A列日期，数据库中是否有该ID卡号对应的相同日期存在，如果有，则显示日期出错。
            List<ConsumerRecordTable> checkExistsList = dao.findByDateDeDepenseAndCarteIdentifiant(formatDateDeepens, importExcelData.getCarteIdentifiant());
            AssertUtil.assertFalse(CollUtil.isNotEmpty(checkExistsList), 7002, "数据已存在");

            //构建数据
            ConsumerRecordModel consumerRecordModel = buildConsumerRecord(importExcelData, formatDateDeepens, adminUserTable);
            consumerRecordModels.add(consumerRecordModel);
        }

        //4.写入数据
        dao.save(ModelUtils.copyListModel(consumerRecordModels, ConsumerRecordTable.class));
        JSONObject json = new JSONObject();
        json.put("successCount", consumerDataList.size());
        return json;
    }

    /**
     * 构造消费数据
     * @param importExcelData
     * @param formatDateDepense
     * @param adminUserTable
     * @return
     */
    private ConsumerRecordModel buildConsumerRecord(NewImportConsumerModel importExcelData,
                                                    String formatDateDepense,
                                                    AdminUserTable adminUserTable) {
        String fournisseur = importExcelData.getFournisseur();
        fournisseur = com.cjack.frenchexcel.util.StringUtils.leaveOneSpace(fournisseur);
        fournisseur = com.cjack.frenchexcel.util.StringUtils.toUpperCase(fournisseur);

        ConsumerRecordModel consumerRecordModel = new ConsumerRecordModel();
        consumerRecordModel.setDateDeDepense(formatDateDepense);
        consumerRecordModel.setMontantTTC(StringUtils.isEmpty(importExcelData.getMontantTTC1()) ? "-" + importExcelData.getMontantTTC2() : importExcelData.getMontantTTC1());
        consumerRecordModel.setCarteIdentifiant(importExcelData.getCarteIdentifiant());
        consumerRecordModel.setCollaborateur(adminUserTable.getJobNumber());
        consumerRecordModel.setImportUserId(adminUserTable.getId());
        consumerRecordModel.setCompanyId(adminUserTable.getCompanyId());
        consumerRecordModel.setFournisseur(fournisseur);
        consumerRecordModel.setUpdateTime(new Date());
        consumerRecordModel.setCreateTime(new Date());

        //查询关联的合作商简称
        if (StrUtil.isNotEmpty(adminUserTable.getJobNumber())) {
            List<CooperativeNumberTable> cooperativeNumberTables = cooperativeNumberDao.findAllByJobNumber(adminUserTable.getJobNumber());
            finish:
            for (CooperativeNumberTable cooperativeNumberTable : cooperativeNumberTables) {
                String nameRule = cooperativeNumberTable.getNameRule() == null ? "" : cooperativeNumberTable.getNameRule();
                nameRule = com.cjack.frenchexcel.util.StringUtils.toUpperCase(nameRule);
                //判断规则修改 名称包含，id不包含
                for (String nameR : nameRule.split(",")) {
                    String fournisseurStr = importExcelData.getFournisseur().toUpperCase();
                    if (fournisseurStr.contains(nameR)) {
                        consumerRecordModel.setFournisseur(cooperativeNumberTable.getName());
                        break finish;
                    }
                }
            }
        }

        return consumerRecordModel;
    }

    /**
     * 获取导入数据
     * @param filePath
     * @return
     * @throws CommonException
     */
    private List<NewImportConsumerModel> getNewImportConsumerModels(String filePath) throws CommonException {
        //需要先将 excel的浏览器端访问路径 转化为服务器端访问路径
        filePath = FileUtils.transferClientFileUrl(filePath, baseClientDir, baseServerDir);

        File excelFile = new File(filePath);
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(excelFile);
        } catch (FileNotFoundException e) {
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR, "找不到文件");
        }
        ExcelLogs logs = new ExcelLogs();
        List<NewImportConsumerModel> importExcelDatas = (List<NewImportConsumerModel>) ExcelUtil.importExcel(NewImportConsumerModel.class, inputStream, "", logs, 0);
        return importExcelDatas;
    }

    /**
     * 把错误的数据筛选分离出来
     *
     * @param importExcelDatas
     * @return
     */
    public void handleFilter(List<ConsumerRecordModel> importExcelDatas) {
        List<ConsumerRecordModel> cycleDatas = new ArrayList<>();
        cycleDatas.addAll(importExcelDatas);
        for (ConsumerRecordModel cycleData : cycleDatas) {
            //判断 MontantTTC和这两个最重要的列不能为空，才算是有效数据
            if (cycleData.getMontantTTC() == null || cycleData.getDateDeDepense() == null) {
                importExcelDatas.remove(cycleData);
            }
        }
    }

    public ConsumerRecordModel getById(Long id) {
        return ModelUtils.copySignModel(dao.findOne(id), ConsumerRecordModel.class);
    }

    public Page<ConsumerRecordTable> list(LayPage page, ConsumerRecordConditionModel condition) {
        Specification<ConsumerRecordTable> specification = handleConditon(condition);
        List<Sort.Order> orders = new ArrayList<>();
        orders.add(new Sort.Order(Sort.Direction.DESC, "dateDeDepense"));
        Pageable pageable = new PageRequest(page.getPage() - 1, page.getLimit(), new Sort(orders));
        Page<ConsumerRecordTable> resultPage = dao.findAll(specification, pageable);
        return resultPage;
    }

    public Page<MooncardTable> listForMooncard(LayPage page) {
        List<Sort.Order> orders = new ArrayList<>();
        orders.add(new Sort.Order(Sort.Direction.DESC, "dateDeDepense"));
        Pageable pageable = new PageRequest(page.getPage() - 1, page.getLimit(), new Sort(orders));
        Specification<MooncardTable> specification = handleConditon(3);
        Page<MooncardTable> resultPage = mooncardDao.findAll(specification, pageable);
        return resultPage;
    }

    /**
     * 查询condition条件吓的所有数据，除了不分页之外，其它返回结果需要痛表格数据的list接口的一致
     *
     * @param condition
     * @return
     * @throws CommonException
     */
    public List<ConsumerRecordModel> list(ConsumerRecordConditionModel condition) {
        Specification<ConsumerRecordTable> specification = handleConditon(condition);
        Sort sort = new Sort(Sort.Direction.ASC, "id");
        List<ConsumerRecordTable> datas = dao.findAll(specification, sort);
        return ModelUtils.copyListModel(datas, ConsumerRecordModel.class);
    }

    /**
     * 查询condition条件吓的所有数据，除了不分页之外，其它返回结果需要痛表格数据的list接口的一致
     *
     * @param condition
     * @return
     * @throws CommonException
     */
    public List<ConsumerRecordModel> listAndSort(ConsumerRecordConditionModel condition) {
        Specification<ConsumerRecordTable> specification = handleConditon(condition);
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        List<ConsumerRecordTable> datas = dao.findAll(specification, sort);
        return ModelUtils.copyListModel(datas, ConsumerRecordModel.class);
    }

    public void add(ConsumerRecordModel model) {
        ConsumerRecordTable table;
        if (model.getId() == null) {
            table = ModelUtils.copySignModel(model, ConsumerRecordTable.class);
        } else {
            table = dao.findOne(model.getId());
            ModelUtils.copySignModel(model, table);
        }
        dao.save(table);
    }

    public void editCooperative(ConsumerRecordModel model) {
        ConsumerRecordTable consumerRecordTable = dao.getOne(model.getId());
        /*
        CooperativeNumberTable cooperativeNumberTable = cooperativeNumberDao.getByName( consumerRecordTable.getFournisseur());
        if( cooperativeNumberTable == null){
            cooperativeNumberTable = cooperativeNumberDao.getByName( model.getFournisseur());
            if( cooperativeNumberTable.getNameRule() == null || !cooperativeNumberTable.getNameRule().contains( consumerRecordTable.getFournisseur())){
                cooperativeNumberTable.setNameRule( cooperativeNumberTable.getNameRule() + "," + consumerRecordTable.getFournisseur());
            }
            if( cooperativeNumberTable.getIdRule() == null || !cooperativeNumberTable.getIdRule().contains( consumerRecordTable.getCollaborateur())){
                cooperativeNumberTable.setIdRule( cooperativeNumberTable.getIdRule() + "," + consumerRecordTable.getCollaborateur());
            }
            cooperativeNumberDao.save( cooperativeNumberTable);
        }*/
        consumerRecordTable.setFournisseur(model.getFournisseur());
        consumerRecordTable.setMontantTTC(model.getMontantTTC());
        dao.save(consumerRecordTable);
    }

    //重置关联云盘的状态
    public void resetCloudDisk(ConsumerRecordModel model) {
        ConsumerRecordTable table = dao.findOne(model.getId());

        if (table.getOtherId() == null || table.getOtherId().equals(0l)) {
            return;
        }
        CloudDiskTable cloudDiskTable = cloudDiskDao.getOne(table.getOtherId());
        cloudDiskTable.setOtherId(null);
        cloudDiskDao.save(cloudDiskTable);

        table.setInvoiceImg("");
        table.setInvoice("");
        table.setOtherId(null);
        table.setInvoiceMoney(null);
        dao.save(table);
    }

    public void reviewInvoiceReject(ConsumerRecordModel model) {
        ConsumerRecordTable consumerRecordTable = dao.getOne(model.getId());
        consumerRecordTable.setInvoiceMoney(null);
        consumerRecordTable.setCustomHouse(null);
        consumerRecordTable.setInvoice(null);
        consumerRecordTable.setInvoiceImg(null);
        dao.save(consumerRecordTable);
    }

    //合并数据
    public void merge(String ids) {
        DecimalFormat df = new DecimalFormat("#.00");
        String[] idArr = ids.split(",");
        BigDecimal total = new BigDecimal(0);
        String newMemo = "";
        for (int i = 0; i < idArr.length; i++) {
            String id = idArr[i];
            ConsumerRecordTable table = dao.getOne(Long.valueOf(id));
            total = total.add(new BigDecimal(table.getMontantTTC()));
            newMemo += DateFormatUtil.format(table.getDateDeDepense(), DateFormatUtil.DATE_RULE_2) + " " + table.getMontantTTC() + ";";
            if (i == idArr.length - 1) {
                if (total.doubleValue() == 0.00d) {
                    //合并结果为0,直接删除
                    dao.delete(table);
                    cloudDiskService.deleteOtherId(table.getId());
                } else {
                    table.setMontantTTC(df.format(total));
                    table.setUpdateTime(new Date());
                    table.setMemo((table.getMemo() == null ? "" : table.getMemo()) + ";" + newMemo);
                    dao.save(table);
                }
            } else {
                dao.delete(table);
                cloudDiskService.deleteOtherId(table.getId());
            }
        }
    }

    //拆分数据
    public void partition(Long id, String moneyOne, String moneyTwo) {
        //修改原数据的金额
        ConsumerRecordTable table = dao.getOne(Long.valueOf(id));
        //如果原来是正数，拆分之后，需要转换成负数
        if (Double.parseDouble(table.getMontantTTC()) < 0) {
            moneyOne = "-" + moneyOne;
            moneyTwo = "-" + moneyTwo;
        }
        table.setMemo(DateFormatUtil.format(table.getDateDeDepense(), DateFormatUtil.DATE_RULE_2) + " " + table.getMontantTTC());
        table.setMontantTTC(moneyOne);
        table.setUpdateTime(new Date());
        dao.save(table);

        //新数据复制原数据
        ConsumerRecordTable newTable = ModelUtils.copySignModel(table, ConsumerRecordTable.class);
        newTable.setMontantTTC(moneyTwo);
        table.setMemo(DateFormatUtil.format(table.getDateDeDepense(), DateFormatUtil.DATE_RULE_2) + " " + table.getMontantTTC());
        newTable.setId(null);
        newTable.setUpdateTime(new Date());
        dao.save(newTable);
    }

    public void uploadInvoice(ConsumerRecordModel model) {
        ConsumerRecordTable table = dao.findOne(model.getId());
        ModelUtils.copySignModel(model, table);
        //保存发票上传时间
        table.setInvoiceUploadTime(new Date());
        dao.save(table);
    }

    public ConsumerRecordModel getLastById(Long id) {
        //查询下一条未审核的消费数据
        ConsumerRecordTable table = dao.getLastById(id);
        if (table == null) {//如果没查询到数据，从从第一条数据从头开始
            table = dao.getLastById(1l);
            if (table == null) {
                return null;
            }
            return ModelUtils.copySignModel(table, ConsumerRecordModel.class);
        }
        return ModelUtils.copySignModel(table, ConsumerRecordModel.class);
    }

    public void del(String ids) {
        List<ConsumerRecordTable> tables = new ArrayList<>();
        String[] idArr = ids.split(",");
        for (String id : idArr) {
            ConsumerRecordTable table = new ConsumerRecordTable();
            table.setId(Long.valueOf(id));
            tables.add(table);
        }
        dao.deleteInBatch(tables);
    }

    public ConsumerRecordTable get(Long id) {
        return dao.getOne(id);
    }

    public ConsumerRecordModel getModel(Long id) {
        return ModelUtils.copySignModel(dao.getOne(id), ConsumerRecordModel.class);
    }

    /**
     * 判断一条数据是否重复
     * 1、先判断今天只能导入今天之天的数据
     * 2、再判断数据库里面是否已经有要导入那天的数据，他们的导入是每天只会导入一次
     * 通过
     *
     * @param model
     * @return 返回true代表有重复数据，返回false代表没有重复数据
     */
    private boolean isRepeat(ConsumerRecordModel model) throws ConsumerImportRepeatException, ParseException {
        String dateDeDepense = model.getDateDeDepense();
        if (dateDeDepense == null) {
            return false;
        }
        Date currDate = new Date(System.currentTimeMillis());
        //如果导入的交易日期 发生在今天 或者今天之后
        if (DateFormatUtil.differentDays(currDate, new Date(dateDeDepense)) >= 0) {
            throw new ConsumerImportRepeatException("导入失败，只能导入今天(不包括今天)之前的消费记录");
        }
        //判断这天的数据是否已经被导入
        List<ConsumerRecordTable> datas = dao.findByDateDeDepense(DateFormatUtil.format(dateDeDepense, DateFormatUtil.DATE_RULE_2));
        if (datas != null && datas.size() != 0) {
            throw new ConsumerImportRepeatException("导入失败，今天的消费记录已经导入");
        }
        return false;
    }

    /**
     * 组装查询条件
     *
     * @param condition
     * @return
     */
    private Specification<ConsumerRecordTable> handleConditon(ConsumerRecordConditionModel condition) {
        Specification<ConsumerRecordTable> specification = new Specification<ConsumerRecordTable>() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                String month = condition.getDealMonth();
                String startTime = condition.getDealStartTime();
                String endTime = condition.getDealEndTime();

                Predicate predicate = cb.conjunction();
                //组装搜索条件
                if (!StringUtils.isEmpty(condition.getImportUserId())) {
                    //处理多选下拉选择的收银员编号
                    List<String> cashierNumbers = Arrays.asList(condition.getImportUserId().split(","));
                    predicate.getExpressions().add(root.<String>get("importUserId").in(cashierNumbers));
                }
                if (!StringUtils.isEmpty(condition.getMoney())) {//模糊搜索
                    predicate.getExpressions().add(cb.like(root.get("montantTTC").as(String.class), "%" + condition.getMoney() + "%"));

                }
                //发票状态
                if (!StringUtils.isEmpty(condition.getInvoiceStatus())) {
                    switch (condition.getInvoiceStatus()) {
                        case "1"://待上传发票
                            predicate.getExpressions().add(cb.isNull(root.get("invoice")));
                            break;
                        case "2"://发票待审核
                            predicate.getExpressions().add(cb.isNotNull(root.get("invoice")));
                            predicate.getExpressions().add(cb.or(cb.notEqual(root.get("invoiceStatus").as(String.class), "PASS"), cb.isNull(root.get("invoiceStatus"))));
                            break;
                        case "3"://发票审核通过
                            predicate.getExpressions().add(cb.equal(root.get("invoiceStatus").as(String.class), "PASS"));
                            break;
                    }
                }
                //月份,选了月份，就按照月份的时间来查询
                if (!StringUtils.isEmpty(month)) {
                    Date[] dates = DateFormatUtil.getTimeByMonth(month);
                    //根据今年月份计算起止日期
                    startTime = DateFormatUtil.format(dates[0], DateFormatUtil.DATE_RULE_3);
                    endTime = DateFormatUtil.format(dates[1], DateFormatUtil.DATE_RULE_3);
                }
                //起始日期
                if (!StringUtils.isEmpty(startTime)) {
                    //前段传过来的之后年月，自己加一个-01
                    predicate.getExpressions().add(cb.greaterThanOrEqualTo(root.get("dateDeDepense").as(String.class), startTime + "-01"));
                }
                //结束日期
                if (!StringUtils.isEmpty(endTime)) {
                    endTime += "-31";
                    //2020-05-29T09:48:54.415Z
                    endTime += "T23:59:59.999Z";
                    predicate.getExpressions().add(cb.lessThanOrEqualTo(root.get("dateDeDepense").as(String.class), endTime));
                }
                //起始日期
                if (!StringUtils.isEmpty(condition.getReviewStartTime())) {
                    predicate.getExpressions().add(cb.greaterThanOrEqualTo(root.get("invoiceReviewTime").as(Date.class), DateFormatUtil.parse(condition.getReviewStartTime() + "-01")));
                }
                //结束日期
                if (!StringUtils.isEmpty(condition.getReviewEndTime())) {
                    String reviewEndTime = condition.getReviewEndTime() + "-01" + " 23:59:59";
                    predicate.getExpressions().add(cb.lessThanOrEqualTo(root.get("invoiceReviewTime").as(Date.class), DateFormatUtil.parseWithMinute(reviewEndTime)));
                }
                //只显示最近6个月的数据  2021-1-14 去掉
                //String limitTime = DateFormatUtil.getTimeCountByMonth();
                //predicate.getExpressions().add( cb.greaterThanOrEqualTo( root.get( "dateDeDepense").as( String.class), limitTime));

                if (condition.getLoginUserId() != null) {
                    //判断权限，判断是否有查询所有数据的权限
                    AdminUserTable adminUserTable = userAdminDao.findOne(condition.getLoginUserId());
                    String roleContent = adminUserTable.getRole().getContent();
                    //如果没有查看所有数据的权限， 则直接根据 记录所属员工id来查询
                    if (!PrivateConfig.checkPrivalege(roleContent, PrivateConfig.CONSUMER_LIST_ALL)) {
                        predicate.getExpressions().add(cb.equal(root.get("importUserId").as(Long.class), adminUserTable.getId()));
                    }
                }
                if (!StringUtils.isEmpty(condition.getCarteIdentifiant())) {
                    predicate.getExpressions().add(cb.like(root.get("carteIdentifiant").as(String.class), "%" + condition.getCarteIdentifiant() + "%"));
                }
                //根据job_number搜索
                if (!StringUtils.isEmpty(condition.getJobNumber())) {
                    predicate.getExpressions().add(cb.like(root.get("collaborateur").as(String.class), "%" + condition.getJobNumber() + "%"));
                }
                //合作商编号[合作商名称]
                if (!StringUtils.isEmpty(condition.getCooperativeSimpleName())) {
                    predicate.getExpressions().add(cb.like(root.get("fournisseur").as(String.class), "%" + condition.getCooperativeSimpleName() + "%"));
                }
                //如果是管理员，则在发票页面只查看上传了发票的数据，发票页面的查询条件有invoice这个条件
                if (!StringUtils.isEmpty(condition.getInvoice())) {
                    predicate.getExpressions().add(root.<String>get("invoice").isNotNull());
                }
                predicate.getExpressions().add(cb.or(cb.lessThan(root.get("checkResAccount").as(Integer.class), 3), cb.isNull(root.get("checkResAccount"))));
                return predicate;
            }
        };
        return specification;
    }

    /**
     * 组装查询条件
     *
     * @param checkResAccount
     * @return
     */
    private Specification<MooncardTable> handleConditon(Integer checkResAccount) {
        Specification<MooncardTable> specification = new Specification<MooncardTable>() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                Predicate predicate = cb.conjunction();
                predicate.getExpressions().add(cb.lessThan(root.get("checkResAccount").as(Integer.class), checkResAccount));
                return predicate;
            }
        };
        return specification;
    }

    /**
     * 统计员工历史的消费总额
     *
     * @param adminUserId
     * @return
     */
    public Double sumByImportUserId(Long adminUserId) {
        Double consumerTotal = dao.sumByImportUserId(adminUserId);
        return consumerTotal;
    }

    /**
     * 统计员工最近35天的消费总额
     *
     * @param adminUserId
     * @return
     */
    public Double sumLastThirtDayTotal(Long adminUserId) {
        String lastThirtDay = DateFormatUtil.formatLastDay(35);
        Double consumerTotal = dao.sumByImportUserIdAndDateDeDebitMore(adminUserId, lastThirtDay);
        return consumerTotal;
    }

    /**
     * 生成发票文件名称，要求返回的格式是 04 2020 0001这种
     *
     * @return
     */
    public String getInvoiceFileName() {
        String res = "";
        //先查询出当月已经上传了多少条 发票了
        int sequence = dao.countInoviceNum();
        //+1代表本条的顺序
        sequence++;
        //在不足4位的前面补0
        String sequenceStr = "0";
        if (sequence < 10) {
            sequenceStr = "000" + sequence;
        } else if (sequence < 100) {
            sequenceStr = "00" + sequence;
        } else if (sequence < 1000) {
            sequenceStr = "0" + sequence;
        } else {
            sequenceStr = "" + sequence;
        }
        String monthStr = "";
        Integer currMonth = DateFormatUtil.getMonth();
        if (currMonth < 10) {
            monthStr = "0" + currMonth;
        } else {
            monthStr = "" + currMonth;
        }
        res += monthStr + " " + DateFormatUtil.getYear() + " " + sequenceStr;
        return res;
    }
}
